/*import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.Semaphore;

public class HillClimber {

	private static final int THREAD_COUNT = 4;
	int[] weights; 
	int nbrSimulationsPerRun;
	int nbrTries;
	PlayerSkeleton bestPlayer = new PlayerSkeleton();

	Semaphore semaphore = new Semaphore(THREAD_COUNT);
	AtomicInteger threadResult = new AtomicInteger();

	private void randWeights()
	{
		Random rand = new Random();
		for (int i = 0; i < weights.length; i++)
			weights[i] = rand.nextInt(40) - 20;
	}

	public synchronized void reportResult(int result)
	{
		threadResult.getAndAdd(result);
		semaphore.release();
	}

	public void run()
	{

		for (int tr = 0; tr < nbrTries; tr++)
		{
			// Start with random weights to optimize hillclimber and prevent
			// it from getting stuck in a local maximum every time.
			randWeights();

			// Holds the globally best result and the corresponding weights
			int best = -1;
			int[] bestW = new int[weights.length];
			for (int i = 0; i < weights.length; i++) bestW[i] = weights[i];

			while (true)
			{
				// Holds the locally best result for this run
				int thisBest = -1;
				int[] thisBestW = new int[weights.length];
				for (int i = 0; i < weights.length; i++) weights[i] = bestW[i];

				// Try to change every weight and observe the new result - keep the change
				// that led to the best average result
				for (int i = 0; i < weights.length; i++)
					for (int j = -7; j <= 7; j++) // Difference in current weight
					{
						weights[i] += j; // update current weight and simulate

						int tot = 0;
						for (int k = 0; k < nbrSimulationsPerRun; k++)
						{
							PlayerSkeleton player = new PlayerSkeleton();
							player.setObserver(this);
							player.setWeights(weights);
							try {semaphore.acquire();}catch(Exception e){}
							(new Thread(player)).start();
						}
						try {semaphore.acquire(THREAD_COUNT);}catch(Exception e){}
						if (threadResult.get() > thisBest) // new local best in this iteration
						{
							bestPlayer.setWeights(weights);
							thisBest = threadResult.get();
							System.out.println("Tried with result: " + thisBest/nbrSimulationsPerRun);
							bestPlayer.printWeights();
							for (int k = 0; k < weights.length; k++) thisBestW[k] = weights[k];
						}
						semaphore.release(THREAD_COUNT);
						threadResult.set(0);
						weights[i] -= j; // reset current weight
					}

				// If we cant optimize further than these weights are the best
				if (thisBest <= best) break;

				// Else this is the best result we have found so far. Try to improve
				// it even further!
				best = thisBest;
				for (int j = 0; j < weights.length; j++) bestW[j] = thisBestW[j];

				System.out.println("Current average: " + best/nbrSimulationsPerRun);
			}				

			// The resulting weights
			System.out.println("Best weights: ");
			for (Feature f: bestPlayer.getFeatures())
				System.out.println(f);
			System.out.println("\n\n");
		}
	}

	public HillClimber(int nbrWeights, int nbrSimulationsPerRun, int nbrTries)
	{
		weights = new int[nbrWeights];
		this.nbrTries = nbrTries;
		this.nbrSimulationsPerRun = nbrSimulationsPerRun;
	}

}*/
